﻿using System;
using System.Data;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace Parichay
{


    /// <summary>
    /// Utilities for use with Parichay.Security and Parichay.Web
    /// </summary>
    public static class Utilities
    {
        private static Object LockTxtLog = new Object();

        /// <summary>
        /// String display for messages with time difference from the current DateTime
        /// e.g.  "1hrs 20min ago"
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static string GetDateTimeForDisplay(DateTime? date)
        {
            if (date == null)
                return string.Empty;
            else
            {
                TimeSpan diff = DateTime.Now - date.Value;

                if (diff.TotalDays < 1)
                    return diff.Hours.ToString() + "hrs " + diff.Minutes.ToString() + "min ago";
                else
                    return date.Value.ToShortDateString() + " " + date.Value.ToShortTimeString();
            }
        }

        /// <summary>
        /// Format DateTime value for easy insertion into Database.
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static string FormatDate(DateTime date)
        {
            return date.ToString("yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// For parsing DateTime string from the format "yyyyMMdd"
        /// </summary>
        /// <param name="dtString">DateTime string in "yyyyMMdd" format</param>
        /// <returns></returns>
        public static DateTime ParseDate(string dtString)
        {
            return DateTime.ParseExact(dtString, "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture);
        }


        /// <summary>
        /// If the current exception is just a wrapper for InnerException, clips the Wrapper exception to 50 characters
        /// If InnerException is not null. Clip the current exception to 50 characters.  
        /// E.g. "Current exception Message...{upto 50characters} + "...->" + InnerException.Message
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        public static string FormatException(Exception ex)
        {
            string message = ex.Message;

            //Add the inner exception if present (showing only the first 50 characters of the first exception)
            if (ex.InnerException != null)
            {
                if (message.Length > 50)
                    message = message.Substring(0, 50);

                message += "...->" + ex.InnerException.Message;
            }

            return message;
        }

        
        /// <summary>
        /// Write message to Text log file
        /// The log file is maintained in the "logs/log.txt" document in the root directory of the application.
        /// </summary>
        /// <param name="Message"></param>
        public static void TextLog(string Message)
        {
            lock (LockTxtLog)
            {
                using (System.IO.StreamWriter sw = new System.IO.StreamWriter(NavHelper.GetPhysicalLocation("logs/log.txt"), true))
                {
                    sw.WriteLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " " + Message);
                }


            }
        }

        public static byte[] CreateAvatar(int sideLength, System.IO.Stream fromStream)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            using (var image = System.Drawing.Image.FromStream(fromStream))
            using (var thumbBitmap = new System.Drawing.Bitmap(sideLength, sideLength))
            {

                var a = Math.Min(image.Width, image.Height);

                var x = (image.Width - a) / 2;

                var y = (image.Height - a) / 2;



                using (var thumbGraph = System.Drawing.Graphics.FromImage(thumbBitmap))
                {

                    thumbGraph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

                    thumbGraph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                    thumbGraph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;



                    var imgRectangle = new System.Drawing.Rectangle(0, 0, sideLength, sideLength);

                    thumbGraph.DrawImage(image, imgRectangle, x, y, a, a, System.Drawing.GraphicsUnit.Pixel);

                    thumbBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

                }

            }
            return (ms.ToArray());

        }

        public static byte[] FileToArray(string sFilePath)
        {
            System.IO.FileStream fs = new System.IO.FileStream(sFilePath,
                System.IO.FileMode.Open, System.IO.FileAccess.Read);
            System.IO.BinaryReader br = new System.IO.BinaryReader(fs);
            Byte[] bytes = br.ReadBytes((Int32)fs.Length);
            br.Close();
            fs.Close();
            return bytes;
        }

        public static byte[] ResizeImage(int newWidth, int newHeight, System.IO.Stream fromStream)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            using (var image = System.Drawing.Image.FromStream(fromStream))
            using (var thumbBitmap = new System.Drawing.Bitmap(newWidth, newHeight))
            {

                int sourceWidth = image.Width;
                int sourceHeight = image.Height;

                float nPercent = 0;
                float nPercentW = 0;
                float nPercentH = 0;

                nPercentW = ((float)newWidth / (float)sourceWidth);
                nPercentH = ((float)newHeight / (float)sourceHeight);

                if (nPercentH < nPercentW)
                    nPercent = nPercentH;
                else
                    nPercent = nPercentW;

                int destWidth = (int)(sourceWidth * nPercent);
                int destHeight = (int)(sourceHeight * nPercent);



                using (var thumbGraph = System.Drawing.Graphics.FromImage(thumbBitmap))
                {

                    thumbGraph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

                    thumbGraph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                    thumbGraph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                    thumbGraph.DrawImage(image, 0, 0, newWidth, newHeight);

                    thumbBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

                }

            }
            return (ms.ToArray());

        }


        public static byte[] CropImage(int cropX, int cropY, int cropWidth, int cropHeight, System.IO.Stream fromStream)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            using (var image = System.Drawing.Image.FromStream(fromStream))
            using (var thumbBitmap = new System.Drawing.Bitmap(cropWidth, cropHeight))
            {


                using (var thumbGraph = System.Drawing.Graphics.FromImage(thumbBitmap))
                {

                    System.Drawing.Rectangle imgRectangle = new System.Drawing.Rectangle(cropX, cropY, cropWidth, cropHeight);

                    thumbGraph.Clear(System.Drawing.Color.Transparent);

                    thumbGraph.DrawImage(image, new System.Drawing.Rectangle(0, 0, cropWidth, cropHeight), imgRectangle, System.Drawing.GraphicsUnit.Pixel);

                    thumbBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

                }

            }
            return (ms.ToArray());

        }



        /// <summary>
        /// Retrieves Physical Application Path for a location
        /// For example "C:\Users\Sam\Documents\Visual Studio 2008\WebSites\parichay\Default.Aspx" for the path "Default.aspx"
        /// </summary>
        /// <param name="path">Physical Path to be appended</param>
        /// <returns></returns>
        public static string GetPhysicalLocation(string path)
        {
            return (System.Web.HttpContext.Current.Request.PhysicalApplicationPath + path);
        }

        /// <summary>
        /// Reads and Input Stream to Byte Array
        /// </summary>
        /// <param name="inputStream"></param>
        /// <returns></returns>
        public static Byte[] readInputStreamToBytes(System.IO.Stream inputStream)
        {
            Byte[] destination = new Byte[inputStream.Length];
            inputStream.Position = 0;
            inputStream.Read(destination, 0, (int)inputStream.Length);
            return destination;
        }

        public static string getConfigSetting(string settingName, string optionalValue)
        {
            string str = System.Configuration.ConfigurationManager.AppSettings[settingName];
                str = (string.IsNullOrEmpty(str)) ? optionalValue:str;
                return str;

        }
    }

    public static class NavHelper
    {
        #region Navigation Helpers

        public static string BaseURL
        {
            get { return HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.ApplicationPath.TrimEnd('/') + '/'; }
        }

        /// <summary>
        /// Retrieves Physical Application Path for a location
        /// For example "C:\Users\Sam\Documents\Visual Studio 2008\WebSites\Parichay.Web\Default.Aspx" for the path "Default.aspx"
        /// </summary>
        /// <param name="path">Physical Path to be appended</param>
        /// <returns></returns>
        public static string GetPhysicalLocation(string path)
        {
            return (System.Web.HttpContext.Current.Request.PhysicalApplicationPath + path);
        }

        /// <summary>
        /// Utility method taken from Eucalypto http: // www.codeproject.com/KB/aspnet/eucalypto.aspx
        /// Build a url based on the page and the parameters specified
        /// </summary>
        /// <param name="page">The page, like page.aspx</param>
        /// <param name="paramTemplate">Must be a format string like forum={0}&id={1}</param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static string BuildUrl(string page, string paramTemplate, params string[] parameters)
        {
            string[] encodedParams;
            if (parameters != null && parameters.Length > 0)
            {
                encodedParams = new string[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                    encodedParams[i] = HttpUtility.UrlEncode(parameters[i]);
            }
            else
            {
                encodedParams = new string[0];
            }

            return page + "?" + string.Format(paramTemplate, encodedParams);
        }

        /// <summary>
        /// Utility method taken from Eucalypto http: // www.codeproject.com/KB/aspnet/eucalypto.aspx
        /// If the path is absolute is return as is, otherwise is combined with AppDomain.CurrentDomain.SetupInformation.ApplicationBase
        /// The path are always server relative path.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string LocateServerPath(string path)
        {
            if (System.IO.Path.IsPathRooted(path) == false)
                path = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, path);

            return path;
        }


        private static string CombineUrl(string baseUrl, string relativeUrl)
        {
            if (relativeUrl.Length == 0 || relativeUrl[0] != '/')
                relativeUrl = '/' + relativeUrl;

            if (baseUrl.Length > 0 && baseUrl[baseUrl.Length - 1] == '/')
                baseUrl = baseUrl.Substring(0, baseUrl.Length - 1);

            return baseUrl + relativeUrl;

            //Uri uriBase = new Uri(baseUrl);
            //Uri uriRelative = new Uri(relativeUrl, UriKind.Relative);
            //Uri uri = new Uri(uriBase, uriRelative);

            //return uri.AbsoluteUri;
        }


        /// <summary>
        /// Utility method taken from Eucalypto http: // www.codeproject.com/KB/aspnet/eucalypto.aspx
        /// Returns an Url to this page that can be used on server side (using ~ notation)
        /// </summary>
        /// <param name="htmlEncode">True to encode the url so can be used without problems inside an xhtml article</param>
        /// <returns></returns>
        public static string GetServerUrl(string Location, bool htmlEncode)
        {
            string url = CombineUrl("~", Location);
            if (htmlEncode)
                url = HttpUtility.HtmlEncode(url);
            return url;
        }

        public static string GetServerUrl(string Location, string Id, bool htmlEncode)
        {
            return BuildUrl(Location, "id={0}", Id);
        }

        /// <summary>
        /// Utility method taken from Eucalypto http: // www.codeproject.com/KB/aspnet/eucalypto.aspx
        /// Returns an absolute client url
        /// </summary>
        /// <param name="htmlEncode">True to encode the url so can be used without problems inside an xhtml article</param>
        /// <returns></returns>
        public static string GetAbsoluteClientUrl(string Location, bool htmlEncode)
        {
            string url = CombineUrl(BaseURL, Location);
            if (htmlEncode)
                url = HttpUtility.HtmlEncode(url);
            return url;
        }

        /// <summary>
        /// Utility method taken from Eucalypto http: // www.codeproject.com/KB/aspnet/eucalypto.aspx
        /// Returns an url to this page that can be used on client side
        /// </summary>
        /// <param name="source"></param>
        /// <param name="htmlEncode">True to encode the url so can be used without problems inside an xhtml article</param>
        /// <returns></returns>
        public static string GetClientUrl(System.Web.UI.Control source, string targetLocation, bool htmlEncode)
        {
            string url = source.ResolveClientUrl(GetServerUrl(targetLocation, false));
            if (htmlEncode)
                url = HttpUtility.HtmlEncode(url);
            return url;
        }

        /// <summary>
        /// Utility method taken from Eucalypto http: // www.codeproject.com/KB/aspnet/eucalypto.aspx
        /// Redirect the response to this page.
        /// </summary>
        /// <param name="source"></param>
        public static void Redirect(System.Web.UI.Control source, string targetLocation)
        {
            source.Page.Response.Redirect(GetServerUrl(targetLocation, false));
        }

        /// <summary>
        /// Utility method taken from Eucalypto http: // www.codeproject.com/KB/aspnet/eucalypto.aspx
        /// User Server.Transfer.
        /// </summary>
        public static void Transfer(string targetLocation)
        {
            System.Web.HttpContext.Current.Server.Transfer(GetServerUrl(targetLocation, false));
        }
        #endregion Navigation Helpers
    }

}
